home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / RCS / icmp.c,v < prev    next >
Encoding:
Text File  |  1990-08-07  |  23.0 KB  |  965 lines

  1. head     1.10;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.10
  10. date     90.08.06.17.17.56;  author mendel;  state Exp;
  11. branches ;
  12. next     1.9;
  13.  
  14. 1.9
  15. date     90.07.10.10.22.52;  author tve;  state Exp;
  16. branches ;
  17. next     1.8;
  18.  
  19. 1.8
  20. date     90.07.09.11.01.10;  author tve;  state Exp;
  21. branches ;
  22. next     1.7;
  23.  
  24. 1.7
  25. date     89.07.23.17.34.44;  author nelson;  state Exp;
  26. branches ;
  27. next     1.6;
  28.  
  29. 1.6
  30. date     89.03.23.09.54.20;  author brent;  state Exp;
  31. branches ;
  32. next     1.5;
  33.  
  34. 1.5
  35. date     89.02.21.10.13.52;  author brent;  state Exp;
  36. branches ;
  37. next     1.4;
  38.  
  39. 1.4
  40. date     88.10.17.09.57.26;  author mendel;  state Exp;
  41. branches ;
  42. next     1.3;
  43.  
  44. 1.3
  45. date     88.08.26.16.34.29;  author mendel;  state Exp;
  46. branches ;
  47. next     1.2;
  48.  
  49. 1.2
  50. date     88.08.16.11.17.03;  author mendel;  state Exp;
  51. branches ;
  52. next     1.1;
  53.  
  54. 1.1
  55. date     88.04.27.08.51.25;  author brent;  state Exp;
  56. branches ;
  57. next     ;
  58.  
  59.  
  60. desc
  61. @ICMP protocol
  62. @
  63.  
  64.  
  65. 1.10
  66. log
  67. @Added byte swapping so ICMP redirects will work on machine with backward
  68. byte sex (ie ds3100).  
  69.  
  70. @
  71. text
  72. @/* 
  73.  * icmp.c --
  74.  *
  75.  *    Routines to handle the ICMP protocol, as specified in RFC 792 
  76.  *    "Internet Control Message Protocol" (Sept. 1981) and RFC 950 
  77.  *    "Internet Standard Subnetting Procedure" (Aug. 1985). 
  78.  *    Incoming packets are validated and an action is taken depending 
  79.  *    of the type of the packet. ICMP packets may be sent to a host 
  80.  *    to indicate errors with the ICMP_SendErrorMsg routine.
  81.  *
  82.  *    Based on 4.3BSD  @@(#)ip_icmp.c 7.6 (Berkeley) 8/31/87
  83.  *
  84.  *     To do: handle
  85.  *     1) routing redirects.
  86.  *     2) source quench.
  87.  *
  88.  * Copyright 1987 Regents of the University of California
  89.  * All rights reserved.
  90.  * Permission to use, copy, modify, and distribute this
  91.  * software and its documentation for any purpose and without
  92.  * fee is hereby granted, provided that the above copyright
  93.  * notice appear in all copies.  The University of California
  94.  * makes no representations about the suitability of this
  95.  * software for any purpose.  It is provided "as is" without
  96.  * express or implied warranty.
  97.  */
  98.  
  99. #ifndef lint
  100. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.9 90/07/10 10:22:52 tve Exp $ SPRITE (Berkeley)";
  101. #endif not lint
  102.  
  103.  
  104. #include "sprite.h"
  105. #include "ipServer.h"
  106. #include "stat.h"
  107. #include "ip.h"
  108. #include "icmp.h"
  109. #include "route.h"
  110. #include "socket.h"
  111. #include "raw.h"
  112.  
  113. static void    Input();
  114. static void    ReturnToSender();
  115. static void    SwapAddresses();
  116.  
  117. /*
  118.  * Names of all ICMP types and names for the UNREACHABLE and REDIRECT codes.
  119.  */
  120. static char     *typeNames[] = {
  121.     "ECHO_REPLY",
  122.     "type 1 - unused",
  123.     "type 2 - unused",
  124.     "UNREACHABLE",
  125.     "SOURCE_QUENCH",
  126.     "REDIRECT",
  127.     "type 6 - unused",
  128.     "type 7 - unused",
  129.     "ECHO",
  130.     "type 9 - unused",
  131.     "type 10 - unused",
  132.     "TIME_EXCEED",
  133.     "PARAM_PROB",
  134.     "TIMESTAMP",
  135.     "TIMESTAMP_REPLY",
  136.     "INFO_REQ",
  137.     "INFO_REPLY",
  138.     "MASK_REQ",
  139.     "MASK_REPLY",
  140. };
  141.  
  142. static char *unreachCodeNames[] = {
  143.     "bad net", 
  144.     "bad host", 
  145.     "bad protocol", 
  146.     "bad port", 
  147.     "need to frag", 
  148.     "src route failed",
  149. };
  150.  
  151. static char *redirectCodeNames[] = {
  152.     "network",
  153.     "host",
  154.     "type of service and network",
  155.     "type of service and host",
  156. };
  157.  
  158.  
  159. /*
  160.  *----------------------------------------------------------------------
  161.  *
  162.  * ICMP_Init --
  163.  *
  164.  *    Establishes the callback routine to handle incoming ICMP packets.
  165.  *
  166.  * Results:
  167.  *    None.
  168.  *
  169.  * Side effects:
  170.  *    A routine will be called whenever a ICMP packet arrives.
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. void
  176. ICMP_Init()
  177. {
  178.     IP_SetProtocolHandler(NET_IP_PROTOCOL_ICMP, Input);
  179. }
  180.  
  181.  
  182. /*
  183.  *----------------------------------------------------------------------
  184.  *
  185.  * Input --
  186.  *
  187.  *    This routine is called whenever an ICMP packet arrives.
  188.  *    Once the packet is validated by checking that the length, checksum
  189.  *    and the type are proper, the type value is used to decide what action 
  190.  *    to take. There are 2 kinds of ICMP types:
  191.  *    1) informational: echo, timestamp, mask and address info requests and
  192.  *        replies.
  193.  *    2) error: unreachable host, net, or port; bad options format;
  194.  *         route redirect, source quench, etc.
  195.  *    The informational requests are handled in a separate routine. 
  196.  *    Informational replies are passed to raw socket handler. The 
  197.  *    error types are handled here and they indicate that there was a 
  198.  *    problem with a packet we have sent.
  199.  *
  200.  * Results:
  201.  *    None.
  202.  *
  203.  * Side effects:
  204.  *    Info request packets are returned to the sender. Error packets pass
  205.  *    information to higher-level protocols. Replies pass to the raw 
  206.  *    socket layer.
  207.  *
  208.  *----------------------------------------------------------------------
  209.  */
  210.  
  211. /*ARGSUSED*/
  212. static void
  213. Input(netID, packetPtr)
  214.     Rte_NetID  netID;        /* ID of the network the packet arrived on. */
  215.     IPS_Packet    *packetPtr;    /* Packet descriptor. */
  216. {
  217.     register Net_ICMPPacket    *icmpPtr;
  218.     register Net_IPHeader    *ipPtr;
  219.     int                dataLen;
  220.     unsigned char        type;
  221.     ReturnStatus        status;
  222.  
  223.     stats.icmp.total++;
  224.  
  225.     /*
  226.      * Determine the start of the ICMP part of the packet. Fill in the
  227.      * packet descriptor in case we need to ship the packet back to the 
  228.      * sender.
  229.      */
  230.  
  231.     ipPtr   = packetPtr->ipPtr;
  232.     icmpPtr = (Net_ICMPPacket *) ((Address)ipPtr + (ipPtr->headerLen * 4));
  233.     packetPtr->data = (Address) icmpPtr;
  234.  
  235.     /*
  236.      * We assume the ipPtr->totalLen is in host byte order.
  237.      */
  238.     dataLen = ipPtr->totalLen - (ipPtr->headerLen * 4);
  239.     packetPtr->dataLen = dataLen;
  240.     packetPtr->ipLen = ipPtr->headerLen * 4;
  241.     packetPtr->hdrLen = 0;
  242.  
  243.     /*
  244.      * Make sure the packet has the proper length.
  245.      */
  246.     if (dataLen < NET_ICMP_MIN_LEN) {
  247.     stats.icmp.shortLen++;
  248.     free(packetPtr->base);
  249.     return;
  250.     }
  251.  
  252.     /*
  253.      * See if the checksum is OK. Since the checksum value in the packet is 
  254.      * not zeroed when calculating the value here, the result should be 0
  255.      * if the packet was not garbled.
  256.      */
  257.     if (Net_InetChecksum(dataLen, (Address) icmpPtr) != 0) {
  258.     stats.icmp.badChecksum++;
  259.     free(packetPtr->base);
  260.     return;
  261.     }
  262.  
  263.     /*
  264.      * Make sure the type is in range before incrementing the counter. 
  265.      * A unknown type is not rejected in order to give the packet
  266.      * to the raw socket layer.  This allows development of new ICMP types.
  267.      */
  268.  
  269.     type = icmpPtr->header.type; 
  270.  
  271.     if  (type > NET_ICMP_MAX_TYPE) {
  272.     stats.icmp.badType++;
  273.     } else {
  274.     stats.icmp.inHistogram[type]++;
  275.     }
  276.  
  277.  
  278.     if (ips_Debug) {
  279.     (void) fprintf(stderr, "ICMP Input: <%x>  <---  <%x>  %s", 
  280.         Net_NetToHostInt(ipPtr->dest), 
  281.         Net_NetToHostInt(ipPtr->source), 
  282.         typeNames[type]);
  283.     if (type ==  NET_ICMP_UNREACHABLE) {
  284.         (void) fprintf(stderr, " -- %s\n", unreachCodeNames[icmpPtr->header.code]);
  285.     } else {
  286.         (void) fprintf(stderr, " -- %d\n", icmpPtr->header.code);
  287.     }
  288.     }
  289.  
  290.     switch (type) {
  291.  
  292.     /*
  293.      * The following types involve the return of some information
  294.      * to the sender. Users don't ever get to see these packets.
  295.      */
  296.  
  297.     case NET_ICMP_ECHO:
  298.     case NET_ICMP_TIMESTAMP:
  299.     case NET_ICMP_INFO_REQ:
  300.     case NET_ICMP_MASK_REQ:
  301.         ReturnToSender(netID, type, dataLen, icmpPtr, packetPtr);
  302.         break;
  303.  
  304.  
  305.  
  306.     /*
  307.      * The following types are feedback about problems with packets
  308.      * that have been sent out. The higher-level protocol that sent
  309.      * the packet needs to be told about the problem.
  310.      */
  311.  
  312.     case NET_ICMP_UNREACHABLE:
  313.         switch (icmpPtr->header.code) {
  314.         case NET_ICMP_UNREACH_NET:
  315.             status = NET_UNREACHABLE_NET;
  316.             break;
  317.  
  318.         case NET_ICMP_UNREACH_HOST:
  319.             status = NET_UNREACHABLE_HOST;
  320.             break;
  321.  
  322.         case NET_ICMP_UNREACH_PROTOCOL:
  323.             status = NET_CONNECT_REFUSED;
  324.             break;
  325.  
  326.         case NET_ICMP_UNREACH_PORT:
  327. #ifdef    REAL_RAW
  328.             if(ips_Debug)
  329.             (void) fprintf(stderr,
  330.                 "ICMP Input: <%x>  <---  <%x> %s -- bad port\n", 
  331.                 Net_NetToHostInt(ipPtr->dest), 
  332.                 Net_NetToHostInt(ipPtr->source), 
  333.                 typeNames[type]);
  334.             Raw_Input(NET_IP_PROTOCOL_ICMP, ipPtr->source, ipPtr->dest, 
  335.                 packetPtr);
  336. #endif    REAL_RAW
  337.             status = NET_CONNECT_REFUSED;
  338.             break;
  339.  
  340.         case NET_ICMP_UNREACH_NEED_FRAG:
  341.             status = FS_BUFFER_TOO_BIG;
  342.             break;
  343.  
  344.         case NET_ICMP_UNREACH_SRC_ROUTE:
  345.             status = NET_UNREACHABLE_HOST;
  346.             break;
  347.  
  348.         default:
  349.             stats.icmp.badCode++;
  350.             status = SUCCESS;
  351.             break;
  352.         }
  353.         if (status != SUCCESS) {
  354.         /*
  355.          * Pass the protocol, destination and the first 64 bits
  356.          * of the data to the error handler.
  357.          */
  358.         int hdrLen = icmpPtr->data.unreach.ipHeader.headerLen * 4;
  359.  
  360.         Sock_ReturnError(status,
  361.             (int)icmpPtr->data.unreach.ipHeader.protocol, 
  362.             icmpPtr->data.unreach.ipHeader.dest,
  363.             (Address) ((Address) &icmpPtr->data.unreach.ipHeader) + 
  364.                     hdrLen);
  365.         }
  366.         break;
  367.  
  368.     /*
  369.      * A source quench packet is sent by a gateway if it ran out of buffers
  370.      * or by a host if we have sent many packets too quickly. We need
  371.      * to cut back on the rate of delivery.
  372.      */
  373.     case NET_ICMP_SOURCE_QUENCH:
  374.         /* To do: pass info to offending protocol layer. */
  375.         break;
  376.  
  377.     /*
  378.      * A gateway has informed us of a shorter path to a destination.
  379.      */
  380.     case NET_ICMP_REDIRECT:
  381.         if (icmpPtr->header.code > NET_ICMP_REDIRECT_TOS_NET) {
  382.         stats.icmp.badCode++;
  383.         } else {
  384.         /*
  385.          * To do: give the information to the routing handler.
  386.          */
  387.         if (icmpPtr->header.code == NET_ICMP_REDIRECT_HOST) {
  388.             Rte_UpdateRoute(
  389.                 Net_NetToHostInt(icmpPtr->data.redirect.ipHeader.dest),
  390.                     icmpPtr->data.redirect.gatewayAddr);
  391.         }
  392.         if (ips_Debug) {
  393.             (void) fprintf(stderr, 
  394.             "ICMP Redirect: %s  new=<%x> old=<%x>\n",
  395.             redirectCodeNames[icmpPtr->header.code],
  396.             icmpPtr->data.redirect.gatewayAddr,
  397.             icmpPtr->data.redirect.ipHeader.dest);
  398.         }
  399.         }
  400.         break;
  401.  
  402. #ifndef    REAL_RAW
  403.     /*
  404.      * The Time Exceeded type is sent when a gateway has found that 
  405.      * a packet's time to live value is 0 or when a host trying to 
  406.      * reassemble a fragmented packet has not received all of the 
  407.      * fragments within a certain amount of time.
  408.      */
  409.     case NET_ICMP_TIME_EXCEED:
  410.         /*
  411.          * This message type is ignored.
  412.          */
  413.         if (icmpPtr->header.code > NET_ICMP_TIME_EXCEED_REASS) {
  414.         stats.icmp.badCode++;
  415.         }
  416.         break;
  417. #endif    REAL_RAW
  418.  
  419.     /*
  420.      * NET_ICMP_PARAM_PROB means there was a problem in the header 
  421.      * parameters of a packet we sent. The packet had to be discarded.
  422.      */
  423.     case NET_ICMP_PARAM_PROB: {
  424.         int hdrLen = icmpPtr->data.param.ipHeader.headerLen * 4;
  425.  
  426.         Sock_ReturnError((ReturnStatus) NET_BAD_OPTION, 
  427.                 (int)icmpPtr->data.param.ipHeader.protocol, 
  428.                 icmpPtr->data.param.ipHeader.dest,
  429.                 (Address)((Address) &icmpPtr->data.param.ipHeader) +
  430.                     hdrLen);
  431.         }
  432.         break;
  433.  
  434.  
  435.     /*
  436.      * The following types must be made available to the clients.
  437.      * Also give packets with unknown types to the clients in case
  438.      * they're using a new type we don't know about yet.
  439.      */
  440. #ifdef    REAL_RAW
  441.     case NET_ICMP_TIME_EXCEED:
  442.         if(ips_Debug)
  443.         (void) fprintf(stderr,
  444.             "ICMP Input: <%x>  <---  <%x> %s\n", 
  445.             Net_NetToHostInt(ipPtr->dest), 
  446.             Net_NetToHostInt(ipPtr->source), 
  447.             typeNames[type]);
  448. #endif    REAL_RAW
  449.     case NET_ICMP_ECHO_REPLY:
  450.     case NET_ICMP_TIMESTAMP_REPLY:
  451.     case NET_ICMP_INFO_REPLY:
  452.     case NET_ICMP_MASK_REPLY:
  453.     default:
  454.         Raw_Input(NET_IP_PROTOCOL_ICMP, ipPtr->source, ipPtr->dest, 
  455.             packetPtr);
  456.     }
  457.     free(packetPtr->base);
  458. }
  459.  
  460.  
  461. /*
  462.  *----------------------------------------------------------------------
  463.  *
  464.  * ReturnToSender --
  465.  *
  466.  *    Handles ICMP echo, timestamp, info request and mask request packets.
  467.  *    The packet is processed and then returned to the sender.
  468.  *
  469.  * Results:
  470.  *    None.
  471.  *
  472.  * Side effects:
  473.  *    A packet is returned to the sender after a bit of processing.
  474.  *
  475.  *----------------------------------------------------------------------
  476.  */
  477.  
  478. static void
  479. ReturnToSender(netID, type, dataLen, icmpPtr, packetPtr)
  480.     Rte_NetID              netID;        /* ID of the network the 
  481.                          * packet came arrived on. */
  482.     unsigned char        type;        /* ICMP type. */
  483.     int                dataLen;    /* Size in bytes of the data
  484.                          * in the packet. */
  485.     register Net_ICMPPacket    *icmpPtr;    /* Ptr to ICMP packet. */
  486.     IPS_Packet    *packetPtr;            /* Packet descriptor. */
  487. {
  488.     register Net_IPHeader *ipHdrPtr = packetPtr->ipPtr;
  489.  
  490.     switch (type) {
  491.  
  492.     /*
  493.      * ECHO: just return the packet as is (but change the type to reply).
  494.      */
  495.     case NET_ICMP_ECHO:
  496.         icmpPtr->header.type = NET_ICMP_ECHO_REPLY;
  497.         break;
  498.  
  499.  
  500.     /*
  501.      * TIMESTAMP: set the times.
  502.      */
  503.     case NET_ICMP_TIMESTAMP:
  504.         if (dataLen < sizeof(Net_ICMPHeader) + sizeof(Net_ICMPDataTime)) {
  505.         stats.icmp.shortLen++;
  506.         return;
  507.         }
  508.         icmpPtr->header.type = NET_ICMP_TIMESTAMP_REPLY;
  509.  
  510.         /*
  511.          * The timestamp should record when we received the packet and
  512.          * when it was sent out.  Just set the transmit time
  513.          * to the receive time -- it'll probably be close enough to
  514.          * the real transmit time...
  515.          */
  516.         icmpPtr->data.timeStamp.recvTime = 
  517.                 Net_HostToNetInt(IPS_GetTimestamp());
  518.         icmpPtr->data.timeStamp.transmitTime = 
  519.                     icmpPtr->data.timeStamp.recvTime;
  520.         break;
  521.  
  522.  
  523.  
  524.     /*
  525.      * INFO: adjust the source address if it was a broadcast.
  526.      */
  527.     case NET_ICMP_INFO_REQ:
  528.         icmpPtr->header.type = NET_ICMP_INFO_REPLY;
  529.         if (Net_InetAddrNetNum(ipHdrPtr->source) == 0) {
  530.         /*
  531.          * Broadcast to this network: 
  532.          */
  533.         ipHdrPtr->source = Net_MakeInetAddr(Rte_GetNetNum(netID), 
  534.                 Net_InetAddrHostNum(ipHdrPtr->source));
  535.         }
  536.         break;
  537.  
  538.  
  539.  
  540.     /*
  541.      * MASK: return the subnet mask for the network the packet came in on.
  542.      */
  543.     case NET_ICMP_MASK_REQ:
  544.         if (dataLen < sizeof(Net_ICMPHeader) + sizeof(Net_ICMPDataMask)) {
  545.         stats.icmp.shortLen++;
  546.         return;
  547.         }
  548.         icmpPtr->header.type = NET_ICMP_MASK_REPLY;
  549.         icmpPtr->data.mask.addrMask = 
  550.                 Net_HostToNetInt(Rte_GetSubnetMask(netID));
  551.  
  552.         /*
  553.          * RFC950 ("Internet Standard Subnetting Procedure") says on p.10 
  554.          * that if the source address is 0, then the destination address 
  555.          * for the reply should be a broadcast address. Since the source 
  556.          * and dest. will swapped below, set the source here.
  557.          */
  558.         if (ipHdrPtr->source == 0) {
  559.         ipHdrPtr->source = Rte_GetBroadcastAddr(netID);
  560.         }
  561.         break;
  562.  
  563.  
  564.  
  565.     default:
  566.         panic("ReturnToSender: bad type %d\n", type);
  567.         return;
  568.         break;
  569.     }
  570.  
  571.  
  572.     /*
  573.      * Swap the source and destination addresses since we're sending 
  574.      * the packet back.
  575.      */
  576.     SwapAddresses(ipHdrPtr);
  577.  
  578.     /*
  579.      * We have to recompute the checksum because of the changes made above.
  580.      */
  581.     icmpPtr->header.checksum = 0;
  582.     icmpPtr->header.checksum = Net_InetChecksum(dataLen, (Address) icmpPtr);
  583.     packetPtr->ipPtr->timeToLive = NET_IP_MAX_TTL;
  584.     (void) IP_Output(packetPtr, FALSE);
  585. }
  586.  
  587. /*
  588.  *----------------------------------------------------------------------
  589.  *
  590.  * ICMP_SendErrorMsg --
  591.  *
  592.  *    Sends an ICMP packet to the source of a bad IP packet.
  593.  *
  594.  * Results:
  595.  *    None.
  596.  *
  597.  * Side effects:
  598.  *    An ICMP error packet is sent to the offending host.
  599.  *
  600.  *----------------------------------------------------------------------
  601.  */
  602.  
  603. void
  604. ICMP_SendErrorMsg(ipHdrPtr, type, code)
  605.     Net_IPHeader    *ipHdrPtr;    /* Ptr to IP header for the packet. */
  606.     int            type;        /* ICMP type to return. */
  607.     int            code;        /* ICMP code to return. */
  608. {
  609.     Net_ICMPPacket    *icmpPtr;
  610.     IPS_Packet        packet;
  611.     int            ipHdrLen;
  612.     Net_InetAddress    dest;
  613.     int            srcRteLen;
  614.     Address        srcRoutePtr;
  615.     int            ipDataLen;
  616.     int            len;
  617.  
  618.     if (type > NET_ICMP_MAX_TYPE) {
  619.     panic("ICMP_SendErrorMsg: bad type: %d\n", type);
  620.     return;
  621.     }
  622.  
  623.     /*
  624.      * Only send an error if the packet is the first fragment.
  625.      */
  626.     if (ipHdrPtr->fragOffset != 0) {
  627.     return;
  628.     }
  629.  
  630.     ipHdrLen = ipHdrPtr->headerLen * 4;
  631.  
  632.     /*
  633.      * Don't send if the packet's protocol was ICMP and the error type is
  634.      * not a redirect and the packet's ICMP type was not an informational
  635.      * type.
  636.      */
  637.     if ((ipHdrPtr->protocol == NET_IP_PROTOCOL_ICMP) &&
  638.     (type != NET_ICMP_REDIRECT)) {
  639.  
  640.     switch (((Net_ICMPHeader *)(((Address) ipHdrPtr) + ipHdrLen))->type) {
  641.         case NET_ICMP_ECHO_REPLY:
  642.         case NET_ICMP_ECHO:
  643.         case NET_ICMP_TIMESTAMP:
  644.         case NET_ICMP_TIMESTAMP_REPLY:
  645.         case NET_ICMP_INFO_REQ:
  646.         case NET_ICMP_INFO_REPLY:
  647.         case NET_ICMP_MASK_REQ:
  648.         case NET_ICMP_MASK_REPLY:
  649.         break;
  650.  
  651.         default:
  652.         return;
  653.         break;
  654.     }
  655.     }
  656.  
  657.  
  658.     /*
  659.      * We need to format an ICMP packet that is composed of
  660.      *    1) an IP header: we use the header + source route options from the 
  661.      *     error packet, with the src and dest addresses swapped.
  662.      *  2) the ICMP header: we use the type and code arguments to this routine.
  663.      *    3) a type-dependent value (an integer).
  664.      *  4) the IP header of the error packet: this includes the basic
  665.      *        header and options.
  666.      *  5) the first 8 octets of data from the error packet.
  667.      *
  668.      * It is assumed that only error-type packets are sent, hence the
  669.      * use of the overlay to include the IP header and data.
  670.      */
  671.  
  672.     IPS_InitPacket(sizeof(Net_ICMPPacket), &packet);
  673.  
  674.     packet.data = packet.dbase + (packet.totalLen - sizeof(Net_ICMPPacket));
  675.     icmpPtr     = (Net_ICMPPacket *) packet.data;
  676.     
  677.     ipDataLen    = ipHdrPtr->totalLen - ipHdrLen;
  678.     len        = ipHdrLen + MIN(8, ipDataLen);
  679.     packet.dataLen = sizeof(Net_ICMPHeader) + sizeof(int) + len;
  680.  
  681.     bcopy( (Address) ipHdrPtr, 
  682.           (Address) &icmpPtr->data.overlay.ipHeader, len);
  683.  
  684.     if (type == NET_ICMP_REDIRECT) {
  685.     icmpPtr->data.redirect.gatewayAddr = 0;
  686.     } else {
  687.     icmpPtr->data.overlay.unused = 0;
  688.     }
  689.     if (type == NET_ICMP_PARAM_PROB) {
  690.     icmpPtr->data.param.paramOffset = code;
  691.     code = 0;
  692.     }
  693.     icmpPtr->header.type = type;
  694.     icmpPtr->header.code = code;
  695.     icmpPtr->header.checksum = 0;
  696.     icmpPtr->header.checksum = Net_InetChecksum(packet.dataLen, 
  697.                     (Address) icmpPtr);
  698.  
  699.     /*
  700.      * Now we format the IP header for the packet. Swap the src and dest
  701.      * addresses since we're returning the packet to the sender.  Include
  702.      * the source-route header options if they're present; other options
  703.      * in the header are not returned.
  704.      */
  705.  
  706.     SwapAddresses(ipHdrPtr);
  707.  
  708.     if (ipHdrLen > sizeof(Net_IPHeader)) {
  709.     srcRoutePtr = IP_GetSrcRoute(&srcRteLen, &dest);
  710.     }
  711.  
  712.     packet.ipLen = sizeof(Net_IPHeader) + srcRteLen;
  713.     packet.ipPtr = (Net_IPHeader *) ((Address) packet.data) - packet.ipLen;
  714.     *packet.ipPtr = *ipHdrPtr;
  715.     if (srcRteLen > 0) {
  716.     bcopy( srcRoutePtr, 
  717.         ((Address) (packet.ipPtr)) + sizeof(Net_IPHeader), srcRteLen);
  718.     free(srcRoutePtr);
  719.     packet.ipPtr->dest = dest;
  720.     }
  721.  
  722.     packet.ipPtr->headerLen = packet.ipLen / 4;
  723.     packet.ipPtr->totalLen = packet.ipLen + packet.dataLen;
  724.     packet.ipPtr->timeToLive = NET_IP_MAX_TTL;
  725.     packet.ipPtr->protocol = NET_IP_PROTOCOL_ICMP;
  726.     (void) IP_Output(&packet, TRUE);
  727.     free(packet.base);
  728. }
  729.  
  730.  
  731. /*
  732.  *----------------------------------------------------------------------
  733.  *
  734.  * SwapAddresses --
  735.  *
  736.  *    Swap the source and destination addresses of an IP header. If the
  737.  *    original destination/new source is a broadcast address, then
  738.  *    change it to our official IP address.
  739.  *
  740.  * Results:
  741.  *    None.
  742.  *
  743.  * Side effects:
  744.  *    The addresses in an IP header are changed.
  745.  *
  746.  *----------------------------------------------------------------------
  747.  */
  748.  
  749. static void
  750. SwapAddresses(ipPtr)
  751.     Net_IPHeader    *ipPtr;
  752. {
  753.     Net_InetAddress    temp;
  754.  
  755.     temp = ipPtr->dest;
  756.     ipPtr->dest = ipPtr->source;
  757.  
  758.     if (Rte_IsBroadcastAddr(temp)) {
  759.     ipPtr->source = Rte_GetOfficialAddr(FALSE);
  760.     } else {
  761.     ipPtr->source = temp;
  762.     }
  763. }
  764. @
  765.  
  766.  
  767. 1.9
  768. log
  769. @just disabled debug printouts (were enabled for REAL_RAW)
  770. @
  771. text
  772. @d29 1
  773. a29 1
  774. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.8 90/07/09 11:01:10 tve Exp Locker: tve $ SPRITE (Berkeley)";
  775. d317 2
  776. a318 1
  777.             Rte_UpdateRoute(icmpPtr->data.redirect.ipHeader.dest,
  778. @
  779.  
  780.  
  781. 1.8
  782. log
  783. @Added a hack to raw sockets: this hack allows user processes which
  784. open a raw socket to send packets which incluse the ip header (i.e.
  785. the ip header is specified by the user process). Currently, the
  786. code only preserves the time-to-live and protocol fields in the
  787. header and fills-in the other ones as usual. This hack is to
  788. support the traceroute program which traces the path taken by ip
  789. packets. It breaks other programs, such as ping, which use raw
  790. sockets. The hack is only enabled if the ipServer is compiled
  791. with REAL_RAW #defined, which is not the default case.
  792. @
  793. text
  794. @d29 1
  795. a29 1
  796. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.7 89/07/23 17:34:44 nelson Exp $ SPRITE (Berkeley)";
  797. d207 1
  798. a207 1
  799.     if (1 || ips_Debug) {
  800. d257 6
  801. a262 5
  802.             (void) fprintf(stderr,
  803.             "ICMP Input: <%x>  <---  <%x> %s -- bad port\n", 
  804.             Net_NetToHostInt(ipPtr->dest), 
  805.             Net_NetToHostInt(ipPtr->source), 
  806.             typeNames[type]);
  807. d370 6
  808. a375 5
  809.         (void) fprintf(stderr,
  810.         "ICMP Input: <%x>  <---  <%x> %s\n", 
  811.         Net_NetToHostInt(ipPtr->dest), 
  812.         Net_NetToHostInt(ipPtr->source), 
  813.         typeNames[type]);
  814. @
  815.  
  816.  
  817. 1.7
  818. log
  819. @Fixed up debugging info.
  820. @
  821. text
  822. @d29 1
  823. a29 1
  824. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.6 89/03/23 09:54:20 brent Exp $ SPRITE (Berkeley)";
  825. a153 1
  826.  
  827. d207 1
  828. a207 1
  829.     if (ips_Debug) {
  830. d256 9
  831. d329 1
  832. d344 1
  833. d367 8
  834. @
  835.  
  836.  
  837. 1.6
  838. log
  839. @Removed stdio.h include
  840. @
  841. text
  842. @d29 1
  843. a29 1
  844. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.5 89/02/21 10:13:52 brent Exp $ SPRITE (Berkeley)";
  845. d210 3
  846. a212 1
  847.         ipPtr->dest, ipPtr->source, typeNames[type]);
  848. @
  849.  
  850.  
  851. 1.5
  852. log
  853. @Updated interface to IP_Output
  854. @
  855. text
  856. @d29 1
  857. a29 1
  858. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/icmp.c,v 1.4 88/10/17 09:57:26 mendel Exp Locker: brent $ SPRITE (Berkeley)";
  859. a40 2
  860.  
  861. #include <stdio.h>
  862. @
  863.  
  864.  
  865. 1.4
  866. log
  867. @Added code for dynamic routing table updates.
  868. @
  869. text
  870. @d29 1
  871. a29 1
  872. static char rcsid[] = "$Header: icmp.c,v 1.3 88/08/26 16:34:29 mendel Exp $ SPRITE (Berkeley)";
  873. d492 1
  874. a492 1
  875.     (void) IP_Output(packetPtr);
  876. d634 1
  877. a634 1
  878.     (void) IP_Output(&packet);
  879. @
  880.  
  881.  
  882. 1.3
  883. log
  884. @Patches for SPUR
  885. @
  886. text
  887. @d29 1
  888. a29 1
  889. static char rcsid[] = "$Header: icmp.c,v 1.2 88/08/16 11:17:03 mendel Exp $ SPRITE (Berkeley)";
  890. d307 4
  891. a310 1
  892.  
  893. @
  894.  
  895.  
  896. 1.2
  897. log
  898. @
  899. @
  900. text
  901. @d29 1
  902. a29 1
  903. static char rcsid[] = "$Header: icmp.c,v 1.1 88/04/27 08:51:25 brent Exp $ SPRITE (Berkeley)";
  904. d579 1
  905. a579 1
  906.     packet.data = packet.base + (packet.totalLen - sizeof(Net_ICMPPacket));
  907. @
  908.  
  909.  
  910. 1.1
  911. log
  912. @Initial revision
  913. @
  914. text
  915. @d29 1
  916. a29 1
  917. static char rcsid[] = "$Header: icmp.c,v 6.0 87/09/08 15:55:26 andrew Stable $ SPRITE (Berkeley)";
  918. d42 1
  919. a42 4
  920. #include "io.h"
  921. #include "sys.h"
  922. #include "mem.h"
  923. #include "byte.h"
  924. d180 1
  925. a180 1
  926.     Mem_Free(packetPtr->base);
  927. d191 1
  928. a191 1
  929.     Mem_Free(packetPtr->base);
  930. d211 1
  931. a211 1
  932.     Io_PrintStream(io_StdErr, "ICMP Input: <%x>  <---  <%x>  %s", 
  933. d214 1
  934. a214 2
  935.         Io_PrintStream(io_StdErr, " -- %s\n", 
  936.             unreachCodeNames[icmpPtr->header.code]);
  937. d216 1
  938. a216 1
  939.         Io_PrintStream(io_StdErr, " -- %d\n", icmpPtr->header.code);
  940. d309 1
  941. a309 1
  942.             Io_PrintStream(io_StdErr, 
  943. d362 1
  944. a362 1
  945.     Mem_Free(packetPtr->base);
  946. d471 1
  947. a471 1
  948.         Sys_Panic(SYS_FATAL, "ReturnToSender: bad type %d\n", type);
  949. d524 1
  950. a524 1
  951.     Sys_Panic(SYS_FATAL, "ICMP_SendErrorMsg: bad type: %d\n", type);
  952. d586 2
  953. a587 2
  954.     Byte_Copy(len, (Address) ipHdrPtr, 
  955.           (Address) &icmpPtr->data.overlay.ipHeader);
  956. d621 3
  957. a623 3
  958.     Byte_Copy(srcRteLen, srcRoutePtr, 
  959.         ((Address) (packet.ipPtr)) + sizeof(Net_IPHeader));
  960.     Mem_Free(srcRoutePtr);
  961. d632 1
  962. a632 1
  963.     Mem_Free(packet.base);
  964. @
  965.